package com.rupertjones.globalcron.web;

import com.rupertjones.globalcron.domain.JobDescriptor;
import net.sourceforge.stripes.action.Before;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.HandlesEvent;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import org.springframework.security.access.prepost.PreAuthorize;

/**
 * <p>&copy Rupert Jones 2011,2012</p>
 *
 * @author rup
 */
@PreAuthorize("hasRole('ROLE_ADMIN')")
public class AddNewJobAction extends AbstractFormAction {

    @ValidateNestedProperties({
        @Validate(field = "name", required = true, on = { "SaveOrUpdate" }),
        @Validate(field = "host", converter = HostConverter.class, required = true, on = { "SaveOrUpdate" }),
        @Validate(field = "script", required = true, on = { "SaveOrUpdate" }),
        @Validate(field = "waitAfter", required = true, on = { "SaveOrUpdate" }, mask = "[0-9]*"),
        @Validate(field = "timezone", required = true, on = { "SaveOrUpdate" }),
        @Validate(field = "cron", required = true, on = { "SaveOrUpdate" }, mask = "(((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9]))|(([0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9]))|([\\?])|([\\*]))[\\s](((([0-9]|[0-5][0-9]),)*([0-9]|[0-5][0-9]))|(([0-9]|[0-5][0-9])(/|-)([0-9]|[0-5][0-9]))|([\\?])|([\\*]))[\\s](((([0-9]|[0-1][0-9]|[2][0-3]),)*([0-9]|[0-1][0-9]|[2][0-3]))|(([0-9]|[0-1][0-9]|[2][0-3])(/|-)([0-9]|[0-1][0-9]|[2][0-3]))|([\\?])|([\\*]))[\\s](((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]),)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)|(([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(/|-)([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)|(L)|(LW)|([1-9]W)|([1-3][0-9]W)|([\\?])|([\\*]))[\\s](((([1-9]|0[1-9]|1[0-2]),)*([1-9]|0[1-9]|1[0-2]))|(([1-9]|0[1-9]|1[0-2])(/|-)([1-9]|0[1-9]|1[0-2]))|(((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC),)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-|/)(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))|([\\?])|([\\*]))[\\s]((([1-7],)*([1-7]))|([1-7](/|-)([1-7]))|(((MON|TUE|WED|THU|FRI|SAT|SUN),)*(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)|((MON|TUE|WED|THU|FRI|SAT|SUN)(-|/)(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)|(([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))?(L|LW)?)|([1-7]#([1-7])?)|([\\?])|([\\*]))(([\\s]19[7-9][0-9])|([\\s]20[0-9]{2}))?")
    })
    private JobDescriptor job;

    @Before(stages = LifecycleStage.BindingAndValidation)
    public void loadAndBind() {
        if (job == null) {
            job = new JobDescriptor();
        }
    }

    public JobDescriptor getJob() {
        return job;
    }

    @DefaultHandler
    public Resolution view() {
        return new ForwardResolution(ADD_JOB_JSP);
    }

    @HandlesEvent("SaveOrUpdate")
    public Resolution onSave() {
        ValidationErrors errors = new ValidationErrors();

        if (!job.scriptExists() && job.runOnThisHost()) {
            errors.add("script", new SimpleError(String.format("The script %s does not exist.", job.getScript())));
        }

        if (errors.isEmpty()) {
            job.setLastModified(System.currentTimeMillis());
            getJobService().save(job);
            return new ForwardResolution(INFO_JOB_ACTION + "?job.id=" + job.getId());
        } else {
            getContext().setValidationErrors(errors);
            return getContext().getSourcePageResolution();
        }
    }
}
